package com.framework.bas.bs.impl;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.jdbc.support.incrementer.AbstractDataFieldMaxValueIncrementer;

import com.framework.bas.bs.IPlmBasBS;
import com.framework.bas.cache.ICache;
import com.framework.bas.dao.IPlmBasDAO;
import com.framework.bas.exception.BasException;
import com.framework.bas.param.QueryParam;
import com.framework.bas.util.CodeBuilder;
import com.framework.bas.util.PlmBasConstant;
import com.framework.bas.util.UtilKey;
import com.framework.bas.vo.BasConstant;
import com.framework.bas.vo.BasSeqKey;
import com.framework.bas.vo.BasService;
import com.framework.dbs.vo.BaseObject;

@SuppressWarnings("unchecked")
public class PlmBasBSImpl implements IPlmBasBS {

	private IPlmBasDAO plmBasDAO;

	private AbstractDataFieldMaxValueIncrementer sequenceGenerator;

	private static final Log log = LogFactory.getLog(PlmBasBSImpl.class);

	/**
	 * 缓存交易
	 */
	private ICache cacheServices;

	/**
	 * 缓存主键
	 */
	private static final Map<String, KeySequence> cacheBasKeys = new HashMap<String, KeySequence>();

	/**
	 * 缓存常量
	 */
	private ICache cacheConstant;

	/**
	 * 缓存统一查询每页记录数
	 */
	private static int cachePageSize = 10;

	private CodeBuilder codeBuilder;

	public CodeBuilder getCodeBuilder() {
		return codeBuilder;
	}

	public void setCodeBuilder(CodeBuilder codeBuilder) {
		this.codeBuilder = codeBuilder;
	}

	public IPlmBasDAO getPlmBasDAO() {
		return plmBasDAO;
	}

	public void setPlmBasDAO(IPlmBasDAO plmBasDAO) {
		this.plmBasDAO = plmBasDAO;
	}

	public AbstractDataFieldMaxValueIncrementer getSequenceGenerator() {
		return sequenceGenerator;
	}

	public void setSequenceGenerator(AbstractDataFieldMaxValueIncrementer sequenceGenerator) {
		this.sequenceGenerator = sequenceGenerator;
	}

	public ICache getCacheServices() {
		return cacheServices;
	}

	public void setCacheServices(ICache cacheServices) {
		this.cacheServices = cacheServices;
	}

	public ICache getCacheConstant() {
		return cacheConstant;
	}

	public void setCacheConstant(ICache cacheConstant) {
		this.cacheConstant = cacheConstant;
	}

	public <T extends BaseObject> int saveByBatch(List<T> list) {
		return this.plmBasDAO.saveByBatch(list);
	}

	public int save(BaseObject object) {
		return this.plmBasDAO.save(object);
	}

	public <T extends BaseObject> int updateByBatch(List<T> list) {
		return this.plmBasDAO.updateByBatch(list);
	}

	public int update(BaseObject object) {
		return this.plmBasDAO.update(object);
	}

	public <T extends BaseObject> T queryById(Class<T> clazz, Serializable id) {
		return this.plmBasDAO.queryById(clazz, id);
	}

	public int delete(BaseObject object) {
		return this.plmBasDAO.delete(object);
	}

	public <T extends BaseObject> int deleteByBatch(List<T> list) {
		return this.plmBasDAO.deleteByBatch(list);
	}

	public int updateHiberateByNamedQuery(String queryId, Object[] param) {
		return this.plmBasDAO.updateHiberateByNamedQuery(queryId, param);
	}

	public int insertIbatisObj(String statementId, Object[] values) {
		return this.plmBasDAO.insertIbatisObj(statementId, values);
	}

	public int deleteIbatisObj(String statementId, Object[] values) {
		return this.plmBasDAO.deleteIbatisObj(statementId, values);
	}

	public int updateIbatisObj(String statementId, Object[] values) {
		return this.plmBasDAO.updateIbatisObj(statementId, values);
	}

	public <T> List<T> query(QueryParam qp) {
		return this.plmBasDAO.query(qp);
	}

	public <T> T queryOne(QueryParam qp) {
		return this.plmBasDAO.queryOne(qp);
	}

	public int querySize(QueryParam qp) {
		return this.plmBasDAO.querySize(qp);
	}

	public <T> List<T> query(String statementId, Object params) {
		QueryParam qp = QueryParam.getInstance2(statementId, params);
		return this.plmBasDAO.query(qp);
	}

	public <T> T queryOne(String statementId, Object params) {
		QueryParam qp = QueryParam.getInstance2(statementId, params);
		return this.plmBasDAO.queryOne(qp);
	}

	public int querySize(String statementId, Object params) {
		QueryParam qp = QueryParam.getInstance2(statementId, params);
		return this.plmBasDAO.querySize(qp);
	}
	
	public Map<String,Object> findOne_JDBC(String s,Object... objs){
		
		return this.plmBasDAO.findOne_JDBC(s,objs);
	}

	/**
	 * 系统初始化进行缓存
	 */
	public void doInit() {
		log.info("PLMBAS开始进行初始化..............");
		// 1缓存常量
//		doCacheConstant();
		// 2分页数
//		doCachePageSize();
		// 3交易信息缓存
		doCacheServices();
		log.info("PLMBAS开始进行完成..............");
	}

	protected void doCacheConstant() {
		cacheConstant.doInit();
	}

	protected void doCacheServices() {
		cacheServices.doInit();
	}

	protected void doCachePageSize() {
		// 查询每页记录数
		BasConstant obj = queryConstantOne(PlmBasConstant.KEY_PAGESIZE);
		if (obj != null) {
			if (obj.getConValue() != null && obj.getConValue().trim().length() > 0) {
				try {
					cachePageSize = Integer.parseInt(obj.getConValue());
				} catch (Throwable t) {
					throw new BasException(t.getMessage());
				}
			}
		}
	}


	public long txNewLongKey(String keyName) {
		KeySequence keySequence = (KeySequence) cacheBasKeys.get(keyName);
		if (keySequence == null) {
			keySequence = new PlmBasBSImpl.KeySequence(plmBasDAO, keyName, sequenceGenerator);
			cacheBasKeys.put(keyName, keySequence);
		}
		return keySequence.getLongKey();
	}

	public String txNewStringKey(String keyName, boolean isFillZero) {
		KeySequence keySequence = (KeySequence) cacheBasKeys.get(keyName);
		if (keySequence == null) {
			keySequence = new PlmBasBSImpl.KeySequence(plmBasDAO, keyName, sequenceGenerator);
			cacheBasKeys.put(keyName, keySequence);
		}
		return keySequence.getStringKey(isFillZero);
	}

	public static class KeySequence {
		private String keyName;
		private String preFix;
		private String subFix;
		private long keyLength;
		private BasSeqKey basKeysVO;
		private IPlmBasDAO basDAO;
		private AbstractDataFieldMaxValueIncrementer basGenerator;

		public KeySequence(IPlmBasDAO basDAO, String keyName, AbstractDataFieldMaxValueIncrementer gen) {
			this.basDAO = basDAO;
			this.keyName = keyName;
			this.basGenerator = gen;
			initKey();
		}

		public long getLongKey() {
			this.basGenerator.setIncrementerName(this.keyName);
			return this.basGenerator.nextLongValue();
		}

		public String getStringKey(boolean isFillZero) {
			StringBuffer keys = new StringBuffer();
			long preFixLength = 0;
			long subFixLength = 0;
			if (StringUtils.isNotBlank(preFix)) {
				preFixLength = preFix.length();
				keys.append(preFix);
			}
			if (StringUtils.isNotBlank(subFix)) {
				subFixLength = subFix.length();
			}
			long result = getLongKey();
			if (isFillZero) {
				for (int i = 1; i <= keyLength - String.valueOf(result).length() - preFixLength - subFixLength; i++) {
					keys.append("0");
				}
			}
			keys.append(result);
			if (subFixLength != 0) {
				keys.append(subFix);
			}
			return keys.toString();
		}

		private void initKey() {
			Map<String, String> param = new HashMap<String, String>();
			param.put("keyName", keyName);
			QueryParam qp = QueryParam.getInstance(BasSeqKey.class, keyName);
			basKeysVO = basDAO.queryOne(qp);
			if (basKeysVO == null) {
				throw new BasException(PlmBasConstant.MSG_0000, new Object[] { keyName });
			}
			keyLength = basKeysVO.getKeyLength().longValue();
			preFix = basKeysVO.getKeyPrefix();
			subFix = basKeysVO.getKeySubfix();
		}
	}

	public BasConstant[] queryConstant(String name) {
		BasConstant[] result = null;
		if (name != null && name.trim().length() > 0) {
			result = (BasConstant[]) cacheConstant.get(name);
		}
		return result != null ? result : new BasConstant[0];
	}

	public BasConstant queryConstantOne(String name) {
		BasConstant[] result = queryConstant(name);
		return result != null && result.length > 0 ? result[0] : null;
	}

	public int queryPageSize() {
		return cachePageSize;
	}

	public BasService queryServiceByCode(String serviceCode) {
		BasService vo = serviceCode != null && serviceCode.trim().length() > 0 ? (BasService) cacheServices.get(serviceCode) : null;
		return vo;
	}

	public BasService[] queryServices() {
		int i = 0;
		BasService[] objs = new BasService[cacheServices.getSize()];
		for (Iterator it = cacheServices.getKeys().iterator(); it.hasNext();) {
			objs[i] = (BasService) cacheServices.get((Serializable) it.next());
			i++;
		}
		return objs;
	}

	/**
	 * 平台框架封装执行存储过程
	 * @param String
	 *            过程名称
	 * @param Map
	 *            系统参数
	 * @return Map 过程结果
	 */
	public Map runProcedure(String procedureName, Map param) {
		return this.getPlmBasDAO().runProcedure(procedureName, param);
	}

	/**
	 * 取得新查询码。
	 * @return String 查询码。
	 */
	public String queryValidId() {
		return String.valueOf(new UtilKey.LongKeyGen().getLongKey());
	}

	/**
	 * 清除系统临时表。
	 * 
	 * @param String
	 *            查询码
	 * @return
	 */
	public void clearTempTable(String validId) {
		Map<String, BigDecimal> param = new HashMap<String, BigDecimal>();
		param.put("I_VALID_ID", new BigDecimal(validId));
		runProcedure("HP_TEMP_CLEAR_PROC", param);
	}

}